#ifndef _PARAM_H
#define _PARAM_H

#include <iostream>
#include <boost/shared_ptr.hpp>

/*
** Parameters that specify svm training and classification
*/

class Parameter
{
public:
    Parameter() : kernel_type(0), m(0), k(0), n(0), s(0), u(0), t(0), st(0), 
                  heldout_sets(0), tree_fragments(0), max_its(0), debug(0), 
                  bipartite(0), tree_depth(0), tree_lambda(0), eps(0), 
                  lbfgs_vecs(0), basis(0), lambda(0), h(0), 
                  em(0), pseudo(false)
                  {}
    unsigned int kernel_type; 

    unsigned int m; // the number of training instances
    unsigned int k; // the number of classes
    unsigned int n; // the number of features
    unsigned int s; // the number of training sequences 
    unsigned int u; // the number of unlabelled training instances


    unsigned int t; // number of testing instances to deduct from m
    unsigned int st; // number of testing sequences to deduct from s
    unsigned int heldout_sets; // number of test sets when cross validating
    unsigned int tree_fragments; // the number of tree features
    unsigned int max_its;
    bool debug;
    bool bipartite;
    int tree_depth;
    double tree_lambda;
    double eps;
    int lbfgs_vecs;

    unsigned int basis; // number of basis functions to approx. kernel 
                        // basis = 0 || basis = m for no approx.
    double lambda;
    double h; // hierarchical kernel weight
    double em; // em iterations
    bool pseudo;
};
typedef boost::shared_ptr<Parameter> ParameterPtr;

class GPParameter: public Parameter
{
public:
    GPParameter() : Parameter(), sigma_sqr(0), poly_kernel_d(0), poly_kernel_r(0), 
                    grbf_kernel_sigma(0), vector_weight(0), tree_weight(0) 
                    {}
    float sigma_sqr; // regulariser variance
    unsigned int poly_kernel_d;
    unsigned int poly_kernel_r;
    float grbf_kernel_sigma;
    float vector_weight;
    float tree_weight;
};
typedef boost::shared_ptr<GPParameter> GPParameterPtr;

inline std::ostream& operator<<(std::ostream &os, const GPParameter &p)
{
    os << "<-------->" << std::endl;
    os << " m = " << p.m << ", n = " << p.n << std::endl;
    os << " sigma_sqr = " << p.sigma_sqr << std::endl;
    os << " max_its = " << p.max_its << std::endl;
    os << " eps = " << p.eps << std::endl;
    os << " lbfgs_vecs = " << p.lbfgs_vecs << std::endl;
    os << " pseudo = " << p.pseudo << std::endl;
    os << "<-------->";

    return os;
}

#endif // _PARAM_H
